package com.transparent;

import java.awt.Color;
import java.awt.Desktop;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class PanelTransparent extends JPanel {
	private JTextField txtRed;
	private JTextField txtGreen;
	private JTextField txtBlue;
	private JLabel lblGreen;
	private JLabel lblBlue;
	private JTextField txtStatus;
	private JButton btnFolderSelect;
	private JButton btnStart;
	final boolean bOpenFolderAfter = false;
	private ProgressDialog progressDialog;
	
	List<String> lstCurDir = new ArrayList<String>();
	List<String> lstPngFiles = new ArrayList<String>();

	private JCheckBox chckbxOverrideSampling;
	private JCheckBox chckbxOpenFolder;

	public PanelTransparent(JFrame parent, String sPanelTitle) {
		setBackground(UIManager.getColor("TableHeader.background"));
		
		progressDialog = new ProgressDialog(parent);
		
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[]{28, 0, 0, 104, 0, 0, 0, 0, 0};
		gridBagLayout.columnWeights = new double[]{0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
		gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0};
		setLayout(gridBagLayout);
		
		setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), sPanelTitle));
		
		JLabel lblRed = new JLabel("R");
		GridBagConstraints gbc_lblRed = new GridBagConstraints();
		gbc_lblRed.insets = new Insets(0, 0, 5, 5);
		gbc_lblRed.gridx = 0;
		gbc_lblRed.gridy = 0;
		add(lblRed, gbc_lblRed);
		
		txtRed = new JTextField();
		txtRed.setEnabled(false);
		txtRed.setToolTipText("'RED' value = 0 - 255");
		GridBagConstraints gbc_txtRed = new GridBagConstraints();
		gbc_txtRed.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtRed.insets = new Insets(0, 0, 5, 5);
		gbc_txtRed.gridx = 1;
		gbc_txtRed.gridy = 0;
		add(txtRed, gbc_txtRed);
		txtRed.setColumns(3);
		
		chckbxOverrideSampling = new JCheckBox("Override Sampling");
		chckbxOverrideSampling.setToolTipText("Manually specify the RGB color when converting to transparent background");
		GridBagConstraints gbc_chckbxOverrideSampling = new GridBagConstraints();
		gbc_chckbxOverrideSampling.anchor = GridBagConstraints.WEST;
		gbc_chckbxOverrideSampling.insets = new Insets(0, 0, 5, 5);
		gbc_chckbxOverrideSampling.gridx = 3;
		gbc_chckbxOverrideSampling.gridy = 0;
		add(chckbxOverrideSampling, gbc_chckbxOverrideSampling);
		
		DefaultTableModel model;
		String col[] = {"PNG List"};
		model = new DefaultTableModel(col,5);
		
		lblGreen = new JLabel("G");
		GridBagConstraints gbc_lblGreen = new GridBagConstraints();
		gbc_lblGreen.insets = new Insets(0, 0, 5, 5);
		gbc_lblGreen.gridx = 0;
		gbc_lblGreen.gridy = 1;
		add(lblGreen, gbc_lblGreen);
		
		txtGreen = new JTextField();
		txtGreen.setEnabled(false);
		txtGreen.setToolTipText("'GREEN' value = 0 - 255");
		GridBagConstraints gbc_txtGreen = new GridBagConstraints();
		gbc_txtGreen.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtGreen.insets = new Insets(0, 0, 5, 5);
		gbc_txtGreen.gridx = 1;
		gbc_txtGreen.gridy = 1;
		add(txtGreen, gbc_txtGreen);
		txtGreen.setColumns(3);
		
		chckbxOpenFolder = new JCheckBox("Open Folder");
		chckbxOpenFolder.setSelected(true);
		chckbxOpenFolder.setToolTipText("Open the 'TRANSPARENT' folder after batch conversion");
		GridBagConstraints gbc_chckbxOpenFolder = new GridBagConstraints();
		gbc_chckbxOpenFolder.anchor = GridBagConstraints.WEST;
		gbc_chckbxOpenFolder.insets = new Insets(0, 0, 5, 5);
		gbc_chckbxOpenFolder.gridx = 3;
		gbc_chckbxOpenFolder.gridy = 1;
		add(chckbxOpenFolder, gbc_chckbxOpenFolder);
		
		lblBlue = new JLabel("B");
		GridBagConstraints gbc_lblBlue = new GridBagConstraints();
		gbc_lblBlue.insets = new Insets(0, 0, 5, 5);
		gbc_lblBlue.gridx = 0;
		gbc_lblBlue.gridy = 2;
		add(lblBlue, gbc_lblBlue);
		
		txtBlue = new JTextField();
		txtBlue.setEnabled(false);
		txtBlue.setToolTipText("'BLUE' value = 0 - 255");
		GridBagConstraints gbc_txtBlue = new GridBagConstraints();
		gbc_txtBlue.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtBlue.insets = new Insets(0, 0, 5, 5);
		gbc_txtBlue.gridx = 1;
		gbc_txtBlue.gridy = 2;
		add(txtBlue, gbc_txtBlue);
		txtBlue.setColumns(3);
		
		btnFolderSelect = new JButton("PNG Folder");
		btnFolderSelect.setToolTipText("Select the folder that contains all the .png files");
		btnFolderSelect.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				lstPngFiles = getPngFolder();
				}
		});
		
		GridBagConstraints gbc_btnFolderSelect = new GridBagConstraints();
		gbc_btnFolderSelect.gridwidth = 2;
		gbc_btnFolderSelect.insets = new Insets(0, 0, 5, 5);
		gbc_btnFolderSelect.gridx = 0;
		gbc_btnFolderSelect.gridy = 4;
		add(btnFolderSelect, gbc_btnFolderSelect);
		
		btnStart = new JButton("Start");
		btnStart.setToolTipText("execute batch conversion. all converted files saved to 'TRANSPARENCY' folder located in above selection");
		btnStart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (lstPngFiles.size() > 0)	
				removeBackgroundColor(lstPngFiles);
				else
					txtStatus.setText("Selected folder does not contain .png files");
			}
		});
		
		GridBagConstraints gbc_btnStart = new GridBagConstraints();
		gbc_btnStart.gridwidth = 2;
		gbc_btnStart.fill = GridBagConstraints.BOTH;
		gbc_btnStart.insets = new Insets(0, 0, 5, 5);
		gbc_btnStart.gridx = 0;
		gbc_btnStart.gridy = 5;
		add(btnStart, gbc_btnStart);
		
		txtStatus = new JTextField(10);
		txtStatus.setText("status");
		txtStatus.setEditable(false);
		GridBagConstraints gbc_txtStatus = new GridBagConstraints();
		gbc_txtStatus.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtStatus.anchor = GridBagConstraints.WEST;
		gbc_txtStatus.gridwidth = 9;
		gbc_txtStatus.gridx = 0;
		gbc_txtStatus.gridy = 7;
		add(txtStatus, gbc_txtStatus);
		

		chckbxOverrideSampling.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				if (chckbxOverrideSampling.isSelected())	{
					txtRed.setEnabled(true);
					txtGreen.setEnabled(true);
					txtBlue.setEnabled(true);
				}
				else	{
					txtRed.setEnabled(false);
					txtGreen.setEnabled(false);
					txtBlue.setEnabled(false);
				}
			}	
			
		});
		
		///error check manual entry
		entryFieldErrChk();
	}
	
	private void removeBackgroundColor(final List<String> pngFiles) {

		progressDialog.setMaximum(100);
		progressDialog.setVisible(true);

		SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {

			@Override
			protected void done() {

				progressDialog.setVisible(false);

			}

			@Override
			protected void process(List<Integer> progress) {

				int percentage = progress.get(progress.size() - 1);

				progressDialog.setValue(percentage);
				progressDialog.setString(Integer.toString(percentage) + "%");

			}

			@Override
			protected Void doInBackground() throws IndexOutOfBoundsException, ParserConfigurationException, SAXException, IOException {

				String sDir = pngFiles.get(0).substring(0, pngFiles.get(0).lastIndexOf("\\"))+"\\TRANSPARENT";
				File dir = new File(sDir);
				
				int i=0;
				
				if (!dir.isDirectory())
					dir.mkdir();

				for (String sFilename : pngFiles) {

					BufferedImage image;
					try {
						image = ImageIO.read(new File(sFilename));

						Color c = new Color(image.getRGB(0,0));
						
						int red = 0;
						int green = 0;
						int blue = 0;

						if (chckbxOverrideSampling.isSelected())	{
							red = Integer.parseInt(txtRed.getText());
							green = Integer.parseInt(txtGreen.getText());
							blue = Integer.parseInt(txtBlue.getText());
						}
						else	{
							red = c.getRed();
							green = c.getGreen();
							blue = c.getBlue();

							txtRed.setText(Integer.toString(red));
							txtGreen.setText(Integer.toString(green));
							txtBlue.setText(Integer.toString(blue));
						}
						
						
						///status bar update
						txtStatus.setText("Exporting: "+sFilename.substring(sFilename.lastIndexOf("\\")+1, sFilename.length()));
						
						image = ImageUtility.makeColorTransparent(sFilename,red,green,blue);
						File out = new File(sDir + sFilename.substring(sFilename.lastIndexOf("\\"), sFilename.length()));
						ImageIO.write(image, "PNG", out);
						
						///progress bar percentage
						publish((int)(Math.round((((float)i)/((float)(pngFiles.size())))*100)));
						i++;
					}
					catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

				///job complete
				txtStatus.setText("Completed!");
				
				///open folder
				if(chckbxOpenFolder.isSelected() && Desktop.isDesktopSupported())	{
					    Desktop.getDesktop().open(dir);
				}
				
				return null;
			}
		};
		///run multi-thread
		worker.execute();
	}
	
	
	
	private List<String> getPngFolder() {

		// JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
		
		JFileChooser chooser;
		
		if (lstCurDir.size()>0)	{
		 	chooser = new JFileChooser(lstCurDir.get(0));
		}
		else	{
			chooser = new JFileChooser(System.getProperty("user.dir"));
			lstCurDir.add("");
		}

		
		List<String> lstPngFiles = new ArrayList<String>();

		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int option = chooser.showOpenDialog(PanelTransparent.this);

		if(option == JFileChooser.APPROVE_OPTION) {
			txtStatus.setText("folder:" + ((chooser.getSelectedFile()!=null)? chooser.getSelectedFile().getAbsoluteFile():"nothing"));
			String sFolderLocation = chooser.getSelectedFile().getAbsoluteFile().toString();
			File nf = new File(sFolderLocation);
			chooser.setCurrentDirectory(nf);
			
			lstCurDir.set(0, chooser.getCurrentDirectory().getAbsolutePath());
//			System.out.println(chooser.getCurrentDirectory().getAbsolutePath());
			
			File[] filesInDirectory = chooser.getCurrentDirectory().listFiles();

			for (File file : filesInDirectory) {
				if(file.getName().toLowerCase().contains(".png"))	{
					lstPngFiles.add(sFolderLocation + "\\" + file.getName());
				}
			}
		}

		if(option == JFileChooser.CANCEL_OPTION) {
			txtStatus.setText("canceled.");
		}
		return lstPngFiles;
	}

	
	private void entryFieldErrChk() {
		
	    ///only allow for max 3 characters
	    final int iTextFieldMax = 3;
	    txtRed.setDocument(new JTextFieldLimit(iTextFieldMax));
	    txtGreen.setDocument(new JTextFieldLimit(iTextFieldMax));
	    txtBlue.setDocument(new JTextFieldLimit(iTextFieldMax));
	    
	    ///allow only numeric values to be entered
	    txtRed.addKeyListener(new KeyAdapter() {
	    	  @Override
	    	  public void keyTyped(KeyEvent e) {
	    	    char c = e.getKeyChar();
	    	    if (!Character.isDigit(c)) {
	    	      e.consume(); // Stop the event from propagating.
	    	    }
	    	  }
	    	});
	    
	    ///allow only numeric values to be entered
	    txtGreen.addKeyListener(new KeyAdapter() {
	    	  @Override
	    	  public void keyTyped(KeyEvent e) {
	    	    char c = e.getKeyChar();
	    	    if (!Character.isDigit(c)) {
	    	      e.consume(); // Stop the event from propagating.
	    	    }
	    	  }
	    	});
	    
	    ///allow only numeric values to be entered
	    txtBlue.addKeyListener(new KeyAdapter() {
	    	  @Override
	    	  public void keyTyped(KeyEvent e) {
	    	    char c = e.getKeyChar();
	    	    if (!Character.isDigit(c)) {
	    	      e.consume(); // Stop the event from propagating.
	    	    }
	    	  }
	    	});
	    
	    ///no values entered over 255
	    txtRed.addFocusListener(new FocusAdapter() {
	    	public void focusLost(FocusEvent arg0) {
	    		if(txtRed.getText().isEmpty())
	    			txtRed.setText("0");
	    		if(Integer.parseInt(txtRed.getText()) > 255) {
	    			txtRed.setText("255");
	    		}
	    	}
	    });
	    
	    ///no values entered over 255
	    txtGreen.addFocusListener(new FocusAdapter() {
	    	public void focusLost(FocusEvent arg0) {
	    		if(txtGreen.getText().isEmpty())
	    			txtGreen.setText("0");
	    		if(Integer.parseInt(txtGreen.getText()) > 255) {
	    			txtGreen.setText("255");
	    		}
	    	}
	    });
	    
	    ///no values entered over 255
	    txtBlue.addFocusListener(new FocusAdapter() {
	    	public void focusLost(FocusEvent arg0) {
	    		if(txtBlue.getText().isEmpty())
	    			txtBlue.setText("0");
	    		if(Integer.parseInt(txtBlue.getText()) > 255) {
	    			txtBlue.setText("255");
	    		}
	    	}
	    });

	}
	
}
